package org.zhxy.zhxy.service.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.xmlbeans.impl.xb.xsdschema.Attribute;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.zhxy.zhxy.dao.UserDao;
import org.zhxy.zhxy.entity.User;
import org.zhxy.zhxy.entity.dto.*;
import org.zhxy.zhxy.exception.WxNotBoundException;
import org.zhxy.zhxy.service.UserService;
import org.zhxy.zhxy.utils.MD5Utils;
import org.zhxy.zhxy.utils.RandomUtils;
import org.zhxy.zhxy.utils.RedisConstants;
import org.zhxy.zhxy.utils.UserHolder;


import javax.annotation.Resource;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 * 项目名称: zhxy
 * 作者: zhaojs
 * 创建日期: 2024年10月20日
 * 文件说明: 见类描述
 */
@Service
public class UserServiceImpl extends ServiceImpl<UserDao, User> implements UserService {

    @Resource
    private UserDao userDao;


    @Resource
    private StringRedisTemplate stringRedisTemplate;

    @Override
    public  void  register(UserRegisterDto userRegisterDto) {
        //校验
        Integer identity = userRegisterDto.getIdentity();
        if (identity == null||(identity!=0&&identity!=1)){
            throw new RuntimeException("身份标识违法");
        }
        String studentId = userRegisterDto.getStudentId();
        if (studentId==null||"".equals(studentId)){
            throw new RuntimeException("学号不能为空");
        }
        String username = userRegisterDto.getUsername();
        if (username==null||"".equals(username)){
            throw new RuntimeException("用户名不能为空");
        }
        String email = userRegisterDto.getEmail();
        if (email==null||"".equals(email)){
            throw new RuntimeException("邮箱不能为空");
        }
        String emailCode = userRegisterDto.getEmailCode();
        if (emailCode==null||"".equals(emailCode)){
            throw new RuntimeException("邮箱验证码不能为空");
        }
        String password = userRegisterDto.getPassword();
        if (password==null||"".equals(password)){
            throw new RuntimeException("密码不能为空");
        }
        synchronized (this){
            //判断是否已经注册
            QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
            //生成验证码
            userQueryWrapper.eq("student_id",studentId);
            userQueryWrapper.eq("identity",identity);
            User user = userDao.selectOne(userQueryWrapper);
            if (user!=null){
                throw new RuntimeException("该用户已注册");
            }
            QueryWrapper<User> userQueryWrapper1 = new QueryWrapper<>();
            userQueryWrapper1.eq("email",email);
            User user1 = userDao.selectOne(userQueryWrapper1);
            if (user1!=null){
                throw new RuntimeException("该邮箱已注册");
            }
            //判断验证码是否正确
            String s = stringRedisTemplate.opsForValue().get("email" + ":" + email);
            if (s==null||!s.equals(emailCode)){
                throw new RuntimeException("验证码已过期或者错误");
            }
            User userInsert = new User();
            userInsert.setEmail(email);
            userInsert.setPassword(MD5Utils.encodeByMd5(password));
            userInsert.setUsername(username);
            userInsert.setStudentId(studentId);
            userInsert.setIdentity(identity);
            userInsert.setCreateTime(new Date());
            userInsert.setUpdateTime(new Date());
            int insert = userDao.insert(userInsert);
            if (insert==0){
                throw new RuntimeException("注册失败");
            }

        }
    }

    @Override
    public String login(UserLoginDto userLoginDto) {
      //校验
        String studentIdOrEmail = userLoginDto.getStudentIdOrEmail();
        if (studentIdOrEmail==null||"".equals(studentIdOrEmail)){
            throw new RuntimeException("学号或邮箱不能为空");
        }
        String password = userLoginDto.getPassword();
        if (password==null||"".equals(password)){
            throw new RuntimeException("密码不能为空");
        }
        QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
        userQueryWrapper.eq("student_id",studentIdOrEmail).or().eq("email",studentIdOrEmail);
        User user = userDao.selectOne(userQueryWrapper);
        if (user==null){
            throw new RuntimeException("用户不存在");
        }
        if (!user.getPassword().equals(MD5Utils.encodeByMd5(password))){
            throw new RuntimeException("密码错误");
        }
        //生成token
        String token = UUID.randomUUID().toString();
        Map<String, String> map = new HashMap<>();
        map.put("id",user.getId().toString());
        map.put("studentId",user.getStudentId());
        map.put("username",user.getUsername());
        map.put("email",user.getEmail());
        map.put("identity",user.getIdentity().toString());
        stringRedisTemplate.opsForHash().putAll(RedisConstants.LOGIN_TOKEN+token,map);
        stringRedisTemplate.expire(RedisConstants.LOGIN_TOKEN+token,RedisConstants.LOGIN_TOKEN_TTL, TimeUnit.HOURS);

        return token;
    }

    @Override
    public void updateInfo(UserUpdateInfo updateInfo) {
        Integer id = UserHolder.getUser().getId();
        User user = new User();
        user.setId(id);
        user.setPhone(updateInfo.getPhone());
        user.setUpdateTime(new Date());
        userDao.updateById(user);

    }

    @Override
    public void updatePassWord(UserUpdatePassWordDto userUpdatePassWordDto) {
        String oldPassWord = userUpdatePassWordDto.getOldPassWord();
        Integer id = UserHolder.getUser().getId();
        QueryWrapper<User>  userQueryWrapper = new QueryWrapper<>();
        userQueryWrapper.eq("id",id);
        User user = userDao.selectOne(userQueryWrapper);
        if (!user.getPassword().equals(MD5Utils.encodeByMd5(oldPassWord))){
            throw new RuntimeException("旧密码错误");
        }
        String newPassWord = MD5Utils.encodeByMd5(userUpdatePassWordDto.getNewPassWord());
        UpdateWrapper<User> userUpdateWrapper = new UpdateWrapper<>();
        userUpdateWrapper.set("password",newPassWord);
        userUpdateWrapper.eq("id",id);
        int update = userDao.update(null, userUpdateWrapper);
        if (update==0){
            throw new RuntimeException("修改密码失败");
        }
    }

    @Override
    public void updateEmail(UserUpdateEmailDto userUpdateEmailDto) {
        User user = UserHolder.getUser();
        //校验
        String email = userUpdateEmailDto.getEmail();
        if (email==null||"".equals(email)){
            throw new RuntimeException("邮箱不能为空");
        }
        String code = userUpdateEmailDto.getCode();
        if (code==null||"".equals(code)){
            throw new RuntimeException("验证码不能为空");
        }
        String emailCode = stringRedisTemplate.opsForValue().get("email" + ":" + email);
         if (emailCode==null||!emailCode.equals(code)){
             throw new RuntimeException("验证码错误或者过期");
         }
         UpdateWrapper<User> userUpdateWrapper = new UpdateWrapper<>();
         userUpdateWrapper.set("email",email);
         userUpdateWrapper.eq("id",user.getId());
         int update = userDao.update(null, userUpdateWrapper);
         if (update==0){
             throw new RuntimeException("修改邮箱失败");
         }
    }

    @Override
    public void bindOpenId(String openId) {
        QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
        userQueryWrapper.eq("open_id",openId);
        User user = userDao.selectOne(userQueryWrapper);
        if (user!=null){
            throw new RuntimeException("该微信已绑定");
        }
        Integer  userId = UserHolder.getUser().getId();
        UpdateWrapper<User> userUpdateWrapper = new UpdateWrapper<>();
        userUpdateWrapper.set("open_id",openId);
        userUpdateWrapper.eq("id",userId);
        int update = userDao.update(null, userUpdateWrapper);
        if (update==0){
            throw new RuntimeException("修改失败");
        }
    }

    @Override
    public String loginByWx(String openId) {
        QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
        userQueryWrapper.eq("open_id",openId);
        User user = userDao.selectOne(userQueryWrapper);
        if (user==null){
          throw new WxNotBoundException("该微信未绑定,请先登录后绑定微信");
        }
        String token = UUID.randomUUID().toString();
        Map<String, String> map = new HashMap<>();
        map.put("id",user.getId().toString());
        map.put("studentId",user.getStudentId());
        map.put("username",user.getUsername());
        map.put("email",user.getEmail());
        map.put("identity",user.getIdentity().toString());
        stringRedisTemplate.opsForHash().putAll(RedisConstants.LOGIN_TOKEN+token,map);
        stringRedisTemplate.expire(RedisConstants.LOGIN_TOKEN+token,RedisConstants.LOGIN_TOKEN_TTL, TimeUnit.HOURS);
        return token;
    }

    @Override
    public void forgetPassword(UserFogetpassWordDto userForgetPasswordDto) {
        String code = userForgetPasswordDto.getCode();
        String email = userForgetPasswordDto.getEmail();
        String studentId = userForgetPasswordDto.getStudentId();
        String password = userForgetPasswordDto.getPassword();
        if (StrUtil.isBlank(code)||StrUtil.isBlank(email)||StrUtil.isBlank(studentId)||StrUtil.isBlank(password)){
            throw new RuntimeException("参数不合法");
        }

        String redisKey = "email" + ":" + email;
        String emailCode = stringRedisTemplate.opsForValue().get(redisKey);
        if (StrUtil.isBlank(emailCode)||!code.equals(emailCode)){
            throw new RuntimeException("验证码错误或者过期");
        }
        QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
        userQueryWrapper.eq("student_id",userForgetPasswordDto.getStudentId());
        User user = userDao.selectOne(userQueryWrapper);
        if (user==null){
            throw new RuntimeException("该用户不存在");
        }
        if (user.getEmail()==null||!user.getEmail().equals(email)){
            throw new RuntimeException("该用户未绑定该邮箱或者邮箱不正确");
        }
        String newPassWord = MD5Utils.encodeByMd5(password);
        UpdateWrapper<User> userUpdateWrapper = new UpdateWrapper<>();
        userUpdateWrapper.set("password",newPassWord);
        userUpdateWrapper.eq("student_id",studentId);
        int update = userDao.update(null, userUpdateWrapper);
        if (update==0){
            throw new RuntimeException("修改密码失败");
        }

    }

    @Override
    public void unbindOpenId() {
        Integer  userId = UserHolder.getUser().getId();
        UpdateWrapper<User> userUpdateWrapper = new UpdateWrapper<>();
        userUpdateWrapper.set("open_id",null);
        userUpdateWrapper.eq("id",userId);
        int update = userDao.update(null, userUpdateWrapper);
        if (update==0){
            throw new RuntimeException("解绑失败");
        }
    }
}
